package com.cwh.taskcenter.task.executor.command;

import com.alibaba.cola.dto.Response;
import com.cwh.taskcenter.domain.engine.rule.executor.RuleExecutor;
import com.cwh.taskcenter.domain.task.gateway.TaskGateWay;
import com.cwh.taskcenter.domain.task.gateway.UserTaskGateWay;
import com.cwh.taskcenter.domain.task.gateway.UserTaskRecordGateWay;
import com.cwh.taskcenter.domain.task.model.BenefitRule;
import com.cwh.taskcenter.domain.task.model.Task;
import com.cwh.taskcenter.domain.task.model.TaskRule;
import com.cwh.taskcenter.domain.task.model.UserTask;
import com.cwh.taskcenter.domain.task.model.UserTaskRecord;
import com.cwh.taskcenter.domain.task.model.UserTaskStatus;
import com.cwh.taskcenter.mq.MessageProducer;
import com.cwh.taskcenter.reward.api.RewardService;
import com.cwh.taskcenter.reward.dto.GrantRewardCmd;
import com.cwh.taskcenter.task.dto.event.TaskCompleteEvent;
import com.cwh.taskcenter.task.dto.event.UserBehaviorEvent;
import com.cwh.taskcenter.task.dto.query.TaskListByEventTypeQry;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.List;

/**
 * @author cwh
 */
@Slf4j
@Component
public class TaskEventHandleExe {

    @Autowired
    private TaskGateWay taskGateWay;

    @Autowired
    private RuleExecutor ruleExecutor;

    @Autowired
    private RewardService rewardService;

    @Autowired
    private UserTaskGateWay userTaskGateWay;

    @Autowired
    private MessageProducer messageProducer;

    @Autowired
    private UserTaskRecordGateWay userTaskRecordGateWay;


    @Transactional(rollbackFor = Exception.class)
    public Response execute(UserBehaviorEvent event) {
        // 1.根据事件类型获取任务
        TaskListByEventTypeQry taskListByEventTypeQry = new TaskListByEventTypeQry();
        taskListByEventTypeQry.setEventType(event.getEventType());
        taskListByEventTypeQry.setUserId(event.getUserId());
        List<Task> taskList = taskGateWay.getTaskByEventType(taskListByEventTypeQry);
        if (CollectionUtils.isEmpty(taskList)) {
            return Response.buildSuccess();
        }

        taskList.stream()
                .filter(this::validateTask)
                .filter(Task::validateUserTask)
                .forEach(task -> processTask(event, task));
        return Response.buildSuccess();
    }


    /**
     * 校验任务，判断是否
     * @param task
     * @return
     */
    private boolean validateTask(Task task) {
        UserTask lastUserTask = task.getLastUserTask();
        // 用户可参与的最大次数
        Integer maxParticipate = task.getMaxParticipate();
        if (maxParticipate != null && maxParticipate > 0) {
            // 获取用户已参与次数
            int count = userTaskGateWay.countByTaskIdAndUserId(task.getId(), lastUserTask.getUserId());
            if (count >= maxParticipate) {
                log.info("用户已参与任务{}的{}次，不能重复参与", task.getId(), maxParticipate);
                return false;
            }
        }
        return true;
    }

    /**
     * 处理任务
     * @param event 事件
     * @param task 任务
     */
    private void processTask(UserBehaviorEvent event, Task task) {
        List<TaskRule> taskRules = task.getTaskRules();
        if (taskRules == null || taskRules.isEmpty()) {
            log.info("任务{}没有规则，不能处理", task.getId());
            return;
        }
        taskRules.forEach(taskRule -> {
            taskRule.setTaskId(task.getId());
            handleTaskRule(event, task,taskRule);
        });

    }

    private void handleTaskRule(UserBehaviorEvent event, Task task,TaskRule taskRule) {
        Boolean isComplete = ruleExecutor.execute(event, taskRule);
        if (task.isAutoClaim()) {
            // 生成用户任务记录
            UserTask userTask = makeUserTask(task, event.getUserId());
            task.setLastUserTask(userTask);
        }
        // 更新用户任务进度
        updateUserTaskProgress(event, task, isComplete);
        // 任务完成，发送奖励
        if (isComplete) {
            // 发送奖励
            grantRewards(task, event);
            // 任务完成，发送完成消息
            sendCompletionNotification(task);
        }
    }

    private void updateUserTaskProgress(UserBehaviorEvent event, Task task, boolean isComplete) {
        // 更新进度
        UserTask userTask = task.getLastUserTask();
        if (userTask != null) {
            int progress = isComplete? 100 : 0;
            userTask.updateProgress(progress);
            Long userTaskId = userTaskGateWay.saveOrUpdate(userTask);
            userTask.setId(userTaskId);
            // 记录用户任务
            userTaskRecordGateWay.save(createUserTaskRecord(event, task.getId(),userTaskId));
        }
    }

    private void grantRewards(Task task, UserBehaviorEvent event) {
        task.getTaskRules()
                .forEach(taskRule -> {
                    taskRule.getBenefits().forEach(benefit ->
                            rewardService.grantReward(createGrantCmd(task, event, benefit))
                    );
                });
    }


    private UserTask makeUserTask(Task task, Long userId) {
        UserTask userTask = new UserTask();
        userTask.setUserId(userId);
        userTask.setTaskId(task.getId());
        userTask.setUserTaskStatus(UserTaskStatus.IN_PROGRESS.name());
        userTask.setProgress(0);
        return userTask;
    }

    private GrantRewardCmd createGrantCmd(Task task, UserBehaviorEvent event, BenefitRule benefit) {
        UserTask lastUserTask = task.getLastUserTask();
        return GrantRewardCmd.builder()
                .taskId(task.getId())
                .userId(event.getUserId())
                .userTaskId(lastUserTask.getId())
                .bizId(event.getBizId())
                .bizType(event.getBizType())
                .title(benefit.getTitle())
                .rewardType(benefit.getRewardType())
                .rewardValue(benefit.getRewardValue())
                .rewardExpireTime(benefit.getRewardExpireTime())
                .rewardDesc(benefit.getRewardDesc())
                .build();
    }

    private UserTaskRecord createUserTaskRecord(UserBehaviorEvent eventRequest,Long taskId,Long userTaskId) {
        // 3.5 准备任务记录
        UserTaskRecord userTaskRecord = new UserTaskRecord();
        userTaskRecord.setUserId(eventRequest.getUserId());
        userTaskRecord.setTaskId(taskId);
        userTaskRecord.setUserTaskId(userTaskId);
        userTaskRecord.setEventType(eventRequest.getEventType());
        userTaskRecord.setEventValue(eventRequest.getBizValue());
        userTaskRecord.setBizId(String.valueOf(eventRequest.getBizId()));
        userTaskRecord.setBizType(eventRequest.getBizType());
        userTaskRecord.setUnionKey(eventRequest.getUuid());
        return userTaskRecord;
    }

    private void sendCompletionNotification(Task task) {
        // 领域事件发布
        UserTask lastUserTask = task.getLastUserTask();
        TaskCompleteEvent taskCompleteEvent = new TaskCompleteEvent();
        taskCompleteEvent.setTaskId(task.getId());
        taskCompleteEvent.setUserId(lastUserTask.getUserId());
        taskCompleteEvent.setTaskName(task.getTaskTitle());
        messageProducer.send("TASK_COMPLETE", task.getId().toString(), taskCompleteEvent);
    }

}
